package com.jxw.cloudpen.web.microsoft;

import com.microsoft.cognitiveservices.speech.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class AzureTTSStreamingExample {
    // 替换为你的Azure语音服务订阅密钥和区域
    private static final String SPEECH_KEY = "bc9a5386c73947948aaaedf6d115f87c";
    private static final String SPEECH_REGION = "southeastasia";
    private static final Logger logger = LogManager.getLogger(AzureTTSStreamingExample.class);
    static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    public static void main(String[] args) throws Exception {
        // 配置语音服务
        SpeechConfig speechConfig = SpeechConfig.fromSubscription(SPEECH_KEY, SPEECH_REGION);
        // 设置语音合成输出格式为PCM
        speechConfig.setSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm);

        // 创建语音合成器，不指定音频输出设备，我们将手动处理音频流
        SpeechSynthesizer synthesizer = new SpeechSynthesizer(speechConfig, null);

        // 要合成的文本
        String text = "欢迎使用微软Azure语音服务的流式语音合成功能。这是一个实时流式播报的示例。你好，你好，今天星期几";
        System.out.println("初始化"+ simpleDateFormat.format(new Date()));
        // 事件处理：当收到合成的音频数据时
        synthesizer.SynthesisStarted.addEventListener((o, e) -> {
            System.out.println("语音合成已开始" + simpleDateFormat.format(new Date()));
        });

        // 处理合成的音频片段
        synthesizer.SynthesisCanceled.addEventListener((o, e) -> {
            System.out.println("语音合成已取消: " + e.getResult().getReason());
        });

        // 处理合成完成事件
        synthesizer.SynthesisCompleted.addEventListener((o, e) -> {
            System.out.println("语音合成已完成"+ simpleDateFormat.format(new Date()));
        });

        // 处理合成的音频数据
        synthesizer.Synthesizing.addEventListener((o, e) -> {
            try {
                // 获取音频数据
                byte[] audioData = e.getResult().getAudioData();
                if (audioData != null && audioData.length > 0) {
                    System.out.println("收到音频数据，长度: " + audioData.length + " bytes" + simpleDateFormat.format(new Date()));
                    // 播放音频片段
                    playAudio(audioData);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });
        // 开始合成（流式）
        System.out.println("开始语音合成..."+ simpleDateFormat.format(new Date()));
        SpeechSynthesisResult result = synthesizer.SpeakTextAsync(text).get();

        // 检查结果
        if (result.getReason() == ResultReason.SynthesizingAudioCompleted) {
            System.out.println("语音合成成功完成"+ simpleDateFormat.format(new Date()));
        } else if (result.getReason() == ResultReason.Canceled) {
            SpeechSynthesisCancellationDetails cancellation = SpeechSynthesisCancellationDetails.fromResult(result);
            System.out.println("语音合成取消: " + cancellation.getReason());
            if (cancellation.getReason() == CancellationReason.Error) {
                System.out.println("错误代码: " + cancellation.getErrorCode());
                System.out.println("错误信息: " + cancellation.getErrorDetails());
            }
        }

        // 释放资源
        result.close();
        synthesizer.close();
    }

    // 播放音频数据
    private static void playAudio(byte[] audioData) throws LineUnavailableException, IOException, UnsupportedAudioFileException {
        // 定义音频格式 (24kHz, 16位, 单声道, 有符号, 小端)
        AudioFormat format = new AudioFormat(24000, 16, 1, true, false);

        // 创建音频输入流
        ByteArrayInputStream bais = new ByteArrayInputStream(audioData);
        AudioInputStream ais = new AudioInputStream(bais, format, audioData.length / format.getFrameSize());

        // 获取音频线路
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
        SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
        line.open(format);
        line.start();

        // 播放音频
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = ais.read(buffer)) != -1) {
            line.write(buffer, 0, bytesRead);
        }

        // 清理资源
        line.drain();
        line.stop();
        line.close();
        ais.close();
        bais.close();
    }
}

